package com.ht.interfaces.init;

import java.lang.reflect.Modifier;
import java.util.Set;

import org.reflections.Reflections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import com.ht.api.db.annotate.HtFunction;
import com.ht.api.db.request.HandleRequestHelper;
import com.ht.api.db.util.FunctionUtil;
import com.ht.interfaces.service.InitService;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;

/**
 * 项目启动后要做的操作
 * @author asq
 * @createTime 2024年12月17日 10:47:07
 */
@Slf4j
@Component
public class ApplicationInitializer {
    @Autowired
    private Environment env;
	
	// 使用单一的初始化方法，严格控制顺序
	@PostConstruct
	private void init() {
		// 是否是生产环境
		boolean isProd = env.matchesProfiles("prod");
		
		// 加载租户数据源
		InitService.loadTenantDataSource();
		
		// 加载所有的专用接口到call表
		if (isProd) {
			HandleRequestHelper.loadFunction();
		}
	}
	
	//加载全部有@HtFunction注解的接口，将所有实现类加载到{@link FunctionUtil}工具类中
	@PostConstruct
	private void loadHtFunctionList() {
		log.info("[init]函数扫描加载开始...");
		int count = 0;
        try {
            // 创建Reflections对象
            Reflections reflections = new Reflections("com.ht");
            
            // 获取包下面的所有有@HtFunction注解的类
            Set<Class<?>> interfaces = reflections.getTypesAnnotatedWith(HtFunction.class);
            for (Class<?> interfaceClass : interfaces) {
                // 验证是否是接口
                if (!interfaceClass.isInterface()) {
                    continue;
                }
                
                // 获取该接口的所有实现类
                Set<?> implementations = reflections.getSubTypesOf(interfaceClass);
                
                // 遍历实现类并实例化
                for (Object impl : implementations) {
                	Class<?> implClass = (Class<?>) impl;
                    try {
                        // 判断是否是抽象类
                        if (Modifier.isAbstract(implClass.getModifiers())) {
                            continue;  // 跳过抽象类
                        }
                    	
                        count ++;
                        FunctionUtil.setFunction(implClass.getSimpleName(), implClass.getDeclaredConstructor().newInstance());
                    } catch (Exception e) {
                        log.error("[init]加载函数失败: {}, 错误: {}", implClass.getName(), e.getMessage(), e);
                    }
                }
            }
                        
        } catch (Exception e) {
            log.error("[init]函数扫描加载失败: {}", e.getMessage(), e);
        }
		log.info("[init]函数扫描加载结束，共加载{}个函数。", count);
    }
}
